package com.wuliu.config;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.wuliu.common.utils.DateUtils;
import com.wuliu.common.utils.ip.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;


/**
 * 通过aop打印控制器入参及返回值
 * author:realue
 */

@Aspect
@Component
@Slf4j
public class LogAopConfig {

    //用来记录请求进入的时间，防止多线程时出错，这里用了ThreadLocal
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    /**
     * 定义切入点，controller下面的所有类的所有公有方法，这里需要更改成自己项目的
     */
    @Pointcut("execution(public * com.wuliu.controller.*.*(..))")
    public void requestLog(){};

    /**
     * 方法之前执行，日志打印请求信息
     * @param joinPoint joinPoint
     */
    @Before("requestLog()")
    public void doBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        //打印当前的请求路径
        log.info("*******************************请求信息*******************************");
        log.info("请求时间:{}", DateUtils.getTime());
        log.info("请求地址:{}", IpUtils.getIpAddr());
        log.info("请求接口:{}", request.getRequestURL());
        log.info("请求参数:{}", Arrays.toString(joinPoint.getArgs()));
        log.info("*******************************请求信息*******************************");
    }

    /**
     * 方法返回之前执行，打印才返回值以及方法消耗时间
     * @param response 返回值
     */
    @AfterReturning(returning = "response",pointcut = "requestLog()")
    public void doAfterRunning(Object response) {
        log.debug("*******************************返回数据*******************************");
        log.info("返回结果:{}", JSON.toJSON(response));
        log.info("返回时间:{}",DateUtils.getTime());
        log.info("请求耗时:{}ms",System.currentTimeMillis()-startTime.get());
        log.debug("*******************************返回数据*******************************");
    }

}
